package com.bangyu.monitor.core.schedule;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.bangyu.monitor.core.common.constant.Const;
import com.bangyu.monitor.core.util.InfluxDbUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.influxdb.dto.QueryResult;
import org.joda.time.DateTime;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: zhangxue
 * @Date: 19/7/12 22:05
 * @Description:
 */
@Component
@Slf4j
public class ExportData {

    private static ThreadPoolExecutor executor = executor = new ThreadPoolExecutor(
            10, 10, 1000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>());


    private String split = ",";


    public void task(String devices){
//        List<String> devices = new ArrayList<>();
//        devices.add("TestEquip001");
//        devices.add("TestEquip002");
//        devices.add("TestEquip003");
//        devices.add("0104711906171");
//        devices.add("0104711906172");
//        devices.add("0104711906173");

        for(String deviceNo:devices.split(",")){
            executor.execute(new Runnable() {
                long now = System.currentTimeMillis();
                long threeHour =  60 * 60 * 1000l;
                private long startTimeLong = (now-threeHour) * Const.MS_NS;

                private long addTime = (60 * 60 * 1000l) * Const.MS_NS;
//                private long addTime = ( 30 * 60 * 1000l) * Const.MS_NS;
                @Override public void run() {
                    while(true){
                        if(!export(deviceNo,startTimeLong,(startTimeLong=startTimeLong+addTime))){
                            break;
                        }
                    }
                }
            });
        }
    }


    private boolean export(String deviceNo, long startDate, long endDate) {
        try{
            log.info("start:"+startDate);
            log.info("end:"+endDate);
            log.info("end-start:"+(endDate-startDate));
            log.info("deviceNo {},startDate {},endDate {}",deviceNo,DateFormatUtils.format((new BigDecimal(startDate).divide(new BigDecimal(Const.MS_NS)).longValue()),"yyyyMMdd HH:mm:ss SSS"),
                    DateFormatUtils.format((new BigDecimal(endDate).divide(new BigDecimal(Const.MS_NS)).longValue()),"yyyyMMdd HH:mm:ss SSS"));
            File file = getFile(deviceNo,DateFormatUtils.format((new BigDecimal(startDate).divide(new BigDecimal(Const.MS_NS)).longValue()),"yyyyMMdd"));

            StringBuilder sb = new StringBuilder(String.format(
                    "select v0,temperature,static_displayment,relative_displayment,bend_value,"
                            + "v1,v2,v3,v4,v5,v6,v7"
                            + " from %s.%s where device_no = '%s' ",
                    Const.INFLUX_RETENTION_POLICY_ONE_HOUR,
                    Const.INFLUX_TABLE_ORIGINAL_DATA, deviceNo));

            sb.append(" and time>" + startDate);
            sb.append(" and time <=" + endDate);
            sb.append(" order by time asc");

            QueryResult queryResult = InfluxDbUtil
                    .query(Const.INFLUX_DATABASE, sb.toString());
            if (CollectionUtils.isNotEmpty(queryResult.getResults())) {
                List<QueryResult.Result> results = queryResult.getResults();
                if (CollectionUtils.isNotEmpty(results)) {
                    QueryResult.Result result = results.get(0);
                    List<QueryResult.Series> seriesList = result.getSeries();
                    if (CollectionUtils.isNotEmpty(seriesList)) {
                        QueryResult.Series series = seriesList.get(0);
                        List<List<Object>> values = series.getValues();
                        StringBuilder sb1 = new StringBuilder();
                        if (CollectionUtils.isNotEmpty(values)) {
                            for (int k = 0; k < values.size(); k++) {
                                List<Object> list = values.get(k);
                                String time = DateFormatUtils
                                        .format(new DateTime(list.get(0).toString())
                                                        .getMillis(),
                                                "yyyyMMdd:HH:mm:ss SSS");
                                sb1.append(time + split
                                                + getVal(list.get(1)) + split
                                                + getVal(list.get(2)) + split
                                                + getVal(list.get(3)) + split
                                                + getVal(list.get(4)) + split
                                                + getVal(list.get(5)) + split
                                                + getVal(list.get(6)) + split
                                                + getVal(list.get(7)) + split
                                                + getVal(list.get(8)) + split
                                                + getVal(list.get(9)) + split
                                                + getVal(list.get(10)) + split
                                                + getVal(list.get(11)) + split
                                                + getVal(list.get(12)) + "\r");
                                if (k!=0 &&(k % 1000 == 0 || k == values.size() - 1)) {

                                    FileUtil.appendString(sb1.toString(), file,
                                            Charset.forName("utf-8"));

                                }
                            }

                        }
                    }else{
                        log.info("{} 结束",deviceNo);
                        return false;
                    }
                }
            }
        }catch (Exception e){
            log.error("error,{}",deviceNo,e);
        }
        return true;

    }

    private Object getVal(Object o) {
        if (o == null) {
            return "";
        }
        if (o instanceof Double) {
            return new BigDecimal((Double) o).setScale(4, RoundingMode.HALF_UP);
        }
        return o.toString();
    }

    private File getFile(String deviceNo,String date) {
        String path = ExportData.class.getResource("").getPath();
        File file = new File(
                "/data/" + deviceNo +"_"+date+ ".txt");
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }
}
